package sale.wxb.loveshopping.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import sale.wxb.loveshopping.entity.yml.YmlConfigAntMatchers;
import sale.wxb.loveshopping.security.AccessDeniedHandlerImpl;
import sale.wxb.loveshopping.security.TokenAuthenticationFilter;

@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private YmlConfigAntMatchers ymlConfigAntMatchers;
    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;
    @Autowired
    private TokenAuthenticationFilter tokenAuthenticationFilter;

    /**
     * 路径匹配由于还需要在过滤器中放行 这里暂仅允许ant风格
     */
    @Bean
    SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                // 关闭csrf
                .csrf().disable()
                // 不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // 允许跨域
                .cors()
                .and()
                // 配置路径是否需要认证
                .authorizeRequests()
                // 认证后允许访问
                .antMatchers(ymlConfigAntMatchers.getAuthenticated().toArray(new String[0])).authenticated()
                // 都允许访问
                .antMatchers(ymlConfigAntMatchers.getPermitAll().toArray(new String[0])).permitAll()
                // 仅允许匿名访问 已登录的不再允许访问
                .antMatchers(ymlConfigAntMatchers.getAnonymous().toArray(new String[0])).anonymous()
                // 除以上配置外其他都需要认证、鉴权
                .anyRequest().authenticated()
                .and()
                // 添加认证过滤器
                .addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                // 配置异常处理
                .exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
